package com.siwei.infoextract.wrapper.parser;

import java.util.LinkedList;
import java.util.List;

import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML.Tag;

public class DomNode {
	private List<DomNode> childNodes = null;
	private DomNode parent;
	private DomNode prevSibling;
	private DomNode nextSibling;
	private String name = null;
	private String attributes = null;
	private Object flag = null;

	private DomNode() {
		this.childNodes = new LinkedList<DomNode>();
		this.flag = null;
	}

	public DomNode(String name, String attributes) {
		this();

		this.name = name;
		this.attributes = attributes;
	}

	public DomNode(Tag tag, MutableAttributeSet attributes) {
		this(tag.toString(), attributes.toString());
	}

	public DomNode getParent() {
		return parent;
	}

	public void setParent(DomNode parent) {
		this.parent = parent;
	}

	public DomNode getPrevSibling() {
		return prevSibling;
	}

	public void setPrevSibling(DomNode prevSibling) {
		this.prevSibling = prevSibling;
	}

	public DomNode getNextSibling() {
		return nextSibling;
	}

	public void setNextSibling(DomNode nextSibling) {
		this.nextSibling = nextSibling;
	}

	// Properties
	//
	public void setFlag(Object flag) {
		this.flag = flag;
	}

	public Object getFlag() {
		return flag;
	}

	public List<DomNode> getNodes() {
		return childNodes;
	}

	public String getName() {
		return name;
	}

	public String getAttributes() {
		return attributes;
	}

	// End Properties

	public void addChild(DomNode node) {
		if (node == null) {
			throw new IllegalArgumentException("The node to insert is null");
		}

		DomNode lastNode = this.getLastChild();		
		if (lastNode != null) {
			lastNode.setNextSibling(node);
			node.setPrevSibling(lastNode);
		}

		childNodes.add(node);
		node.setParent(this);
	}

	public void addChild(DomNode insertBefore, DomNode node) {
		if (node == null) {
			throw new IllegalArgumentException("The node to insert is null");
		}

		if (insertBefore == null) {
			addChild(node);
			return;
		}

		int index = childNodes.indexOf(insertBefore);		
		if (index == -1) {
			addChild(node);
			return;
		}

		DomNode prevSibling = insertBefore.getPrevSibling();
		if (prevSibling != null) {
			prevSibling.setNextSibling(node);
		}

		insertBefore.setPrevSibling(node);
		
		childNodes.add(index, node);
		node.setParent(this);
		node.setNextSibling(insertBefore);
		node.setPrevSibling(prevSibling);
	}

	public void removeChild(int index) {
		DomNode node = (DomNode)childNodes.get(index);
		DomNode prevSibling = node.getPrevSibling();
		DomNode nextSibling = node.getNextSibling();
		
		if (prevSibling != null) {
			prevSibling.setNextSibling(nextSibling);
		}
		
		if (nextSibling != null) {
			prevSibling.setPrevSibling(prevSibling);
		}

		childNodes.remove(node);		
	}

	public void removeChild(DomNode domNode) {
		DomNode prevSibling = domNode.getPrevSibling();
		DomNode nextSibling = domNode.getNextSibling();

		if (prevSibling != null) {
			prevSibling.setNextSibling(nextSibling);
		}
		
		if (nextSibling != null) {
			nextSibling.setPrevSibling(prevSibling);
		}

		childNodes.remove(domNode);
	}
	
	public DomNode getChild(int index) {
		return childNodes.get(index);
	}

	public DomNode getFirstChild() {
		if (this.getChildrenCount() > 0) {
			return childNodes.get(0);
		} else {
			return null;
		}
	}

	public DomNode getLastChild() {
		int childrenCount = this.getChildrenCount();

		if (childrenCount > 0) {
			return this.getChild(childrenCount - 1);
		} else {
			return null;
		}
	}

	public int getChildrenCount() {
		return childNodes.size();
	}

	public void clear() {
		childNodes.clear();
	}

	public String toString() {
		return "name:" + this.name + " value:" + this.attributes;
	}
}
